package com.scalpel.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * “压缩解压”工具类
 *
 * @author huanglw
 * @date  2016-10-20
 *
 * History: [修改人][时间][修改描述]
 */
public class ZipUtil {


    /**
     * 压缩文件
     *
     * @param zipOutputStream
     * @param file 要压缩的文件
     * @param zipName 压缩后的文件名
     * @throws IOException
     */
    private void zipFile(ZipOutputStream zipOutputStream, File file, String zipName) throws IOException {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            // 把需要压缩的文件写入到压缩目录中
            zipOutputStream.putNextEntry(new ZipEntry(zipName));

            byte[] bytes = new byte[1024];
            int length = -1;
            while ((length = fileInputStream.read(bytes)) != -1) {
                zipOutputStream.write(bytes, 0, length);
            }
        } finally {
            if (zipOutputStream != null) {
                zipOutputStream.closeEntry();
            }
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        }
    }

    /**
     * 压缩文件夹
     *
     * @param zipOutputStream
     * @param file 要压缩的文件
     * @param zipName 压缩后的文件名
     * @throws IOException
     */
    private void zipDirectory(ZipOutputStream zipOutputStream, File file, String zipName) throws IOException {

        if (file.isDirectory()) {
            File[] subFiles = file.listFiles();
            // 如何子文件为空的话，那么就只有空文件，加个"/"代表文件夹
            if (subFiles.length == 0) {
                zipOutputStream.putNextEntry(new ZipEntry(zipName+"/"));
            }
            for (File subFile : subFiles) {
                if (subFile.isFile()){
                    zipFile(zipOutputStream, subFile, zipName+"/"+subFile.getName());
                } else {
                    // 地柜调用
                    zipDirectory(zipOutputStream, subFile, zipName+"/"+subFile.getName());
                }
            }
        }
    }

    /**
     * 压缩文件
     *
     * @param srcPath 源文件
     * @param desPath 目标文件
     * @throws IOException
     */
    public static void zip(String srcPath, String desPath) throws IOException {
        File file = new File(srcPath);
        FileOutputStream fileOutputStream = new FileOutputStream(desPath);
        ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
        ZipUtil zipUtil = new ZipUtil();
        if (file.isDirectory()) {
            zipUtil.zipDirectory(zipOutputStream, file, file.getName());
        } else {
            zipUtil.zipFile(zipOutputStream, file, file.getName());
        }
    }

    /**
     * 解压文件
     *
     * @param srcPath 源路径
     * @param desPath 目标路径
     * @throws IOException
     */
    public static void unZip(String srcPath, String desPath) throws IOException {

        FileInputStream fileInputStream = null;
        ZipInputStream zipInputStream = null;
        ZipEntry zipEntry = null;
        try {
            fileInputStream = new FileInputStream(srcPath);
                // 目标文件对象
                File file = new File(desPath + File.separator + zipEntry.getName());
                zipInputStream = new ZipInputStream(fileInputStream);
                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                // 如果父节文件不存在，那么创建父文件
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                // 如果是一个文件夹
                if (zipEntry.isDirectory()) {
                    if (!file.exists()) {
                        file.mkdir();
                    }
                } else {
                    // 如果是一个文件，那么需要再铺设一个流，这边读文件，那么写文件
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    byte[] buff = new byte[1024];;//加快速度，设置一个1024字节的缓冲区
                    int length = -1;
                    while ((length = zipInputStream.read(buff)) != -1) {
                        fileOutputStream.write(buff, 0, length);
                    }
                    zipInputStream.closeEntry();
                    fileOutputStream.close();
                }
            }
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (zipInputStream != null){
                zipInputStream.close();
            }
        }
    }

    public static void main(String[] args) {
        try {
            zip("D:\\opt","D:\\opt.zip");
            unZip("D:\\opt.zip","D:\\ttt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
